// ------------------------------------------------------------------------
// 项目名称：Canroc.Net
// 版权归属：Canroc（https://gitee.com/canroc）
// 
// 许可证信息
// Canroc.Net项目主要遵循 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-APACHE 文件。
// 
// 使用条款：
// 1.使用本项目应遵守相关法律法规和许可证的要求。
// 2.不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动。
// 3.任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Canroc.Net 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// ------------------------------------------------------------------------

namespace Canroc.Net.Core.Helper;

/// <summary>
///     HttpContext 辅助工具类
/// </summary>
public static class HttpContextHelper
{
    /// <summary>
    ///     从请求的 User-Agent 提取浏览器名称与主版本号
    /// </summary>
    /// <param name="context">HTTP 上下文</param>
    /// <returns>如 "Chrome 126"；无法识别返回 "Unknown"。</returns>
    public static string GetBrowserInfo(HttpContext? context)
    {
        if (context?.Request == null) return "Unknown";

        var userAgent = context.Request.Headers.UserAgent.ToString();
        if (string.IsNullOrWhiteSpace(userAgent)) return "Unknown";

        var (browser, version) = GetBrowserAndVersion(userAgent);
        if (string.IsNullOrWhiteSpace(browser) || string.Equals(browser, "Unknown", StringComparison.OrdinalIgnoreCase))
            return "Unknown";

        return string.IsNullOrWhiteSpace(version) ||
               string.Equals(version, "Unknown", StringComparison.OrdinalIgnoreCase)
            ? browser
            : $"{browser} {version}";
    }

    /// <summary>
    ///     从请求的 User-Agent 提取操作系统与设备类型信息
    /// </summary>
    /// <param name="context">HTTP 上下文</param>
    /// <returns>如 "Windows 11 Desktop"；无法识别返回 "Unknown"。</returns>
    public static string GetOsInfo(HttpContext? context)
    {
        if (context?.Request == null) return "Unknown";

        var headers = context.Request.Headers;
        var userAgent = headers.UserAgent.ToString();
        if (string.IsNullOrWhiteSpace(userAgent)) return "Unknown";

        var (os, osVersion, device) = GetOsAndDevice(userAgent);
        if (string.IsNullOrWhiteSpace(os) || string.Equals(os, "Unknown", StringComparison.OrdinalIgnoreCase))
            return "Unknown";

        var parts = new List<string>(3) { os };
        if (!string.IsNullOrWhiteSpace(osVersion) &&
            !string.Equals(osVersion, "Unknown", StringComparison.OrdinalIgnoreCase))
            parts.Add(osVersion);
        if (!string.IsNullOrWhiteSpace(device) && !string.Equals(device, "Unknown", StringComparison.OrdinalIgnoreCase))
            parts.Add(device);

        return string.Join(' ', parts);
    }

    /// <summary>
    ///     从 User-Agent 解析浏览器名称与主版本号
    /// </summary>
    /// <param name="userAgent">User-Agent 字符串</param>
    /// <returns>浏览器名称与主版本号（browser, version）</returns>
    private static (string browser, string version) GetBrowserAndVersion(string userAgent)
    {
        var ua = userAgent.ToLowerInvariant();

        if (ua.Contains("edg")) // Edge: Edg/、EdgiOS/、EdgA/
        {
            return ("Edge", ExtractFirstVersion(userAgent, "Edg/", "EdgiOS/", "EdgA/"));
        }

        if (ua.Contains("opr/") || ua.Contains("opera")) // Opera: OPR/ 或老的 Opera/
        {
            return ("Opera", ExtractFirstVersion(userAgent, "OPR/", "Opera/"));
        }

        if (ua.Contains("crios")) // iOS 上的 Chrome: CriOS/
        {
            return ("Chrome", ExtractVersion(userAgent, "CriOS/"));
        }

        if (ua.Contains("chrome") && !ua.Contains("edg"))
        {
            return ("Chrome", ExtractVersion(userAgent, "Chrome/"));
        }

        if (ua.Contains("fxios")) // iOS 上的 Firefox: FxiOS/
        {
            return ("Firefox", ExtractVersion(userAgent, "FxiOS/"));
        }

        if (ua.Contains("firefox"))
        {
            return ("Firefox", ExtractVersion(userAgent, "Firefox/"));
        }

        if (ua.Contains("samsungbrowser"))
        {
            return ("Samsung Internet", ExtractVersion(userAgent, "SamsungBrowser/"));
        }

        if (ua.Contains("yabrowser"))
        {
            return ("Yandex", ExtractVersion(userAgent, "YaBrowser/"));
        }

        if (ua.Contains("vivaldi"))
        {
            return ("Vivaldi", ExtractVersion(userAgent, "Vivaldi/"));
        }

        if (ua.Contains("safari") && !ua.Contains("chrome") && !ua.Contains("crios") && !ua.Contains("fxios") &&
            !ua.Contains("edg"))
        {
            return ("Safari", ExtractVersion(userAgent, "Version/"));
        }

        return ("Unknown", "Unknown");
    }

    /// <summary>
    ///     从 User-Agent 解析操作系统、版本与设备类型（不依赖 UA Client Hints）。
    /// </summary>
    /// <param name="userAgent">User-Agent 字符串</param>
    /// <returns>操作系统、版本与设备类型（os, osVersion, device）。</returns>
    private static (string os, string osVersion, string device) GetOsAndDevice(string userAgent)
    {
        var ua = userAgent.ToLowerInvariant();
        string os = "Unknown";
        string osVersion = "Unknown";
        string device = "Desktop";

        // 设备类型
        if (ua.Contains("mobile") || ua.Contains("iphone") || ua.Contains("android"))
            device = "Mobile";
        else if (ua.Contains("tablet") || ua.Contains("ipad"))
            device = "Tablet";

        // 操作系统
        if (ua.Contains("windows nt 10.0"))
        {
            os = "Windows 10/11"; // 传统 UA 无法区分 10 与 11
        }
        else if (ua.Contains("windows nt 6.3"))
        {
            os = "Windows 8.1";
        }
        else if (ua.Contains("windows nt 6.2"))
        {
            os = "Windows 8";
        }
        else if (ua.Contains("windows nt 6.1"))
        {
            os = "Windows 7";
        }
        else if (ua.Contains("windows nt 6.0"))
        {
            os = "Windows Vista";
        }
        else if (ua.Contains("mac os x"))
        {
            os = "macOS";
            osVersion = ExtractMacVersion(userAgent);
        }
        else if (ua.Contains("iphone") || ua.Contains("ipad"))
        {
            os = "iOS";
            osVersion = ExtractIosVersion(userAgent);
        }
        else if (ua.Contains("android"))
        {
            os = "Android";
            osVersion = ExtractAndroidVersion(userAgent);
        }
        else if (ua.Contains("linux"))
        {
            os = "Linux";
        }

        return (os, osVersion, device);
    }

    /// <summary>
    ///     尝试按多个前缀优先匹配提取版本主号
    /// </summary>
    /// <param name="userAgent">User-Agent 字符串</param>
    /// <param name="patterns">版本前缀集合，如 "Edg/"、"OPR/"。</param>
    /// <returns>主版本号，失败返回 "Unknown"。</returns>
    private static string ExtractFirstVersion(string userAgent, params string[] patterns)
    {
        foreach (var p in patterns)
        {
            int i = userAgent.IndexOf(p, StringComparison.OrdinalIgnoreCase);
            if (i >= 0) return ExtractVersion(userAgent, p);
        }

        return "Unknown";
    }

    /// <summary>
    ///     按指定前缀提取版本主号
    /// </summary>
    /// <param name="userAgent">User-Agent 字符串</param>
    /// <param name="pattern">版本前缀，如 "Chrome/"</param>
    /// <returns>主版本号，失败返回 "Unknown"。</returns>
    private static string ExtractVersion(string userAgent, string pattern)
    {
        try
        {
            int startIndex = userAgent.IndexOf(pattern, StringComparison.OrdinalIgnoreCase);
            if (startIndex < 0) return "Unknown";

            startIndex += pattern.Length;
            int endIndex = userAgent.IndexOf(' ', startIndex);
            if (endIndex == -1) endIndex = userAgent.Length;

            string version = userAgent.Substring(startIndex, endIndex - startIndex);
            return version.Split('.')[0]; // 取主版本号
        }
        catch
        {
            return "Unknown";
        }
    }

    /// <summary>
    ///     从 User-Agent 提取 macOS 版本
    /// </summary>
    /// <param name="userAgent">User-Agent 字符串</param>
    /// <returns>macOS 版本，失败返回 "Unknown"。</returns>
    private static string ExtractMacVersion(string userAgent)
    {
        try
        {
            int startIndex = userAgent.IndexOf("Mac OS X ", StringComparison.Ordinal);
            if (startIndex < 0) return "Unknown";

            startIndex += 9; // "Mac OS X " 长度
            int endIndex = userAgent.IndexOf(';', startIndex);
            if (endIndex == -1) endIndex = userAgent.IndexOf(')', startIndex);
            if (endIndex <= startIndex) return "Unknown";

            return userAgent.Substring(startIndex, endIndex - startIndex).Replace('_', '.');
        }
        catch
        {
            return "Unknown";
        }
    }

    /// <summary>
    ///     从 User-Agent 提取 iOS 版本
    /// </summary>
    /// <param name="userAgent">User-Agent 字符串</param>
    /// <returns>iOS 版本，失败返回 "Unknown"。</returns>
    private static string ExtractIosVersion(string userAgent)
    {
        try
        {
            int startIndex = userAgent.IndexOf("OS ", StringComparison.Ordinal);
            if (startIndex < 0) return "Unknown";

            startIndex += 3;
            int endIndex = userAgent.IndexOf(' ', startIndex);
            if (endIndex == -1) endIndex = userAgent.IndexOf('_', startIndex);
            return endIndex <= startIndex
                ? "Unknown"
                : userAgent.Substring(startIndex, endIndex - startIndex).Replace('_', '.');
        }
        catch
        {
            return "Unknown";
        }
    }

    /// <summary>
    ///     从 User-Agent 提取 Android 版本
    /// </summary>
    /// <param name="userAgent">User-Agent 字符串</param>
    /// <returns>Android 版本，失败返回 "Unknown"。</returns>
    private static string ExtractAndroidVersion(string userAgent)
    {
        try
        {
            int startIndex = userAgent.IndexOf("Android ", StringComparison.Ordinal);
            if (startIndex < 0) return "Unknown";

            startIndex += 8;
            int endIndex = userAgent.IndexOf(';', startIndex);
            return endIndex <= startIndex ? "Unknown" : userAgent.Substring(startIndex, endIndex - startIndex);
        }
        catch
        {
            return "Unknown";
        }
    }
}